package com.ww.springboot.boot.utils;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.pdf.*;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateExceptionHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ClassPathResource;
import org.xhtmlrenderer.pdf.ITextFontResolver;
import org.xhtmlrenderer.pdf.ITextRenderer;

import java.io.*;
import java.util.Map;
import java.util.Optional;

/**
 * 基于 itext5
 *
 * @author wanwei
 * @since 2021-01-09 09:08
 */
@Slf4j
public class PdfUtils {

	public static byte[] create(String htmlStr) {
		ByteArrayOutputStream outputStream = null;
		try {
			ITextRenderer renderer = new ITextRenderer();
			// 如果携带图片则加上以下代码,将图片标签转换为Itext自己的图片对象
			renderer.getSharedContext().setReplacedElementFactory(new Base64ImgReplacedElementFactory());
			renderer.getSharedContext().getTextRenderer().setSmoothingThreshold(0);
			renderer.setDocumentFromString(htmlStr);
			outputStream = new ByteArrayOutputStream();
			ITextFontResolver fontResolver = renderer.getFontResolver();
			ClassPathResource classPathResource = new ClassPathResource("/static/font/msyh.ttc");
			String pathIn = classPathResource.getPath();
			log.info("字体路径：------------------------------------------", pathIn);
			fontResolver.addFont(pathIn, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
			//泰国字体
			classPathResource = new ClassPathResource("/static/font/FreeSerif.ttf");
			pathIn = classPathResource.getPath();
			fontResolver.addFont(pathIn, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
			renderer.layout();
			renderer.createPDF(outputStream);
		} catch (Exception e) {
			log.info("pdf生成失败", e);
			throw new RuntimeException(e);
		} finally {
			try {
				if (outputStream != null) {
					outputStream.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return outputStream.toByteArray();
	}


	public static byte[] handingPdf(byte[] bytes, TextDto textDto) {
		bytes = PdfUtils2.zoom(bytes);
		ByteArrayOutputStream outputStream = null;
		try {
			PdfReader pdfReader = new PdfReader(new ByteArrayInputStream(bytes));
			outputStream = new ByteArrayOutputStream();
			PdfStamper stamper = new PdfStamper(pdfReader, outputStream);

			addTextDto(textDto, pdfReader, stamper);

			stamper.close();
		} catch (Exception e) {
			log.info("pdf生成失败", e);
			throw new RuntimeException(e);
		} finally {
			try {
				if (outputStream != null) {
					outputStream.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return outputStream.toByteArray();
	}


	public static byte[] addPage(byte[] bytes, NewPageDTO newPageDTO) {
		if (newPageDTO == null) {
			return bytes;
		}
		Map<String, Object> map = newPageDTO.getMap();
		ByteArrayOutputStream outputStream = null;
		PdfReader pdfReader = null;
		try {
			outputStream = new ByteArrayOutputStream();
			pdfReader = new PdfReader(bytes);
			Document document = new Document(pdfReader.getPageSize(1));
			map.put("width", document.getPageSize().getWidth());
			map.put("height", document.getPageSize().getHeight());
			PdfCopy copy = new PdfCopy(document, outputStream);
			document.open();
			for (int j = 1; j <= pdfReader.getNumberOfPages(); j++) {
				document.newPage();
				PdfImportedPage page = copy.getImportedPage(pdfReader, 1);
				copy.addPage(page);
			}
			byte[] bytesNew = PdfUtils.create(generateHtml(newPageDTO.getPackagePath(), newPageDTO.getFileName(), newPageDTO.getMap()));
			pdfReader = new PdfReader(bytesNew);
			document.newPage();
			PdfImportedPage page = copy.getImportedPage(pdfReader, 1);
			copy.addPage(page);
			document.close();
		} catch (Exception e) {
			log.info("pdf生成失败", e);
			throw new RuntimeException(e);
		} finally {
			try {
				if (outputStream != null) {
					outputStream.close();
				}
				if (pdfReader != null) {
					pdfReader.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return outputStream.toByteArray();
	}


	private static void addTextDto(TextDto textDto, PdfReader pdfReader, PdfStamper stamper) throws DocumentException, IOException {
		if (textDto == null) {
			return;
		}
		for (int i = 1; i <= pdfReader.getNumberOfPages(); i++) {
			PdfContentByte overContent = stamper.getOverContent(i);

			//添加文字
			BaseFont font = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
			overContent.beginText();
			overContent.setFontAndSize(font, textDto.getFontSize());
			overContent.setTextMatrix(10, 10);
			overContent.setLineWidth(0f);
			overContent.setTextRenderingMode(PdfContentByte.TEXT_RENDER_MODE_FILL_STROKE);
			overContent.showTextAligned(Element.ALIGN_CENTER, "-" + Optional.ofNullable(textDto.getText()).orElse(""),
				pdfReader.getCropBox(i).getLeft() + textDto.getX(), pdfReader.getCropBox(i).getBottom() + textDto.getY(), 0);
			overContent.endText();
		}
	}

	public static void createLocal(String htmlStr, String path) {
		OutputStream outputStream = null;
		try {
			ITextRenderer renderer = new ITextRenderer();
			// 如果携带图片则加上以下代码,将图片标签转换为Itext自己的图片对象
			renderer.getSharedContext().setReplacedElementFactory(new Base64ImgReplacedElementFactory());
			renderer.getSharedContext().getTextRenderer().setSmoothingThreshold(0);
			renderer.setDocumentFromString(htmlStr);
			outputStream = new FileOutputStream(path);
			ITextFontResolver fontResolver = renderer.getFontResolver();
			ClassPathResource classPathResource = new ClassPathResource("/static/font/msyh.ttc");
			String pathIn = classPathResource.getPath();
			log.info("字体路径：------------------------------------------{}", pathIn);
			fontResolver.addFont(pathIn, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
			//泰国字体
			classPathResource = new ClassPathResource("/static/font/FreeSerif.ttf");
			pathIn = classPathResource.getPath();
			fontResolver.addFont(pathIn, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);

			renderer.layout();
			renderer.createPDF(outputStream);
		} catch (Exception e) {
			log.info("pdf生成失败", e);
			throw new RuntimeException(e);
		} finally {
			try {
				outputStream.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

//		ByteArrayOutputStream baos = new ByteArrayOutputStream();
//		try {
//			ITextRenderer renderer = new ITextRenderer();
//			ITextFontResolver fontResolver = renderer.getFontResolver();
//			//支持中文
//			fontResolver.addFont("/static/font/msyh.ttc", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
//			renderer.setDocumentFromString(htmlStr);
//			renderer.layout();
//			renderer.createPDF(baos);
////			out.flush();
//			FileUtil.writeBytes(baos.toByteArray(),path);
//			// 临时测试用途
//		} catch (Exception e) {
//			log.info("pdf生成失败", e);
//			throw new RuntimeException(e);
//		} finally {
//			try {
//				baos.close();
//			} catch (IOException e) {
//				e.printStackTrace();
//			}
//		}
	}

	/**
	 * @param packagePath 模板包路径
	 * @param name        模板名(带后缀)
	 * @param map         数据源
	 * @return
	 * @throws IOException
	 */
	public static String generateHtml(String packagePath, String name, Map<String, Object> map) {
		Configuration cfg = new Configuration(Configuration.VERSION_2_3_23);
		Writer out = new StringWriter();
		try {
			cfg.setClassLoaderForTemplateLoading(PdfUtils.class.getClassLoader(), packagePath);
			cfg.setDefaultEncoding("UTF-8");
			cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
			cfg.setLogTemplateExceptions(false);
			//获取模板文件
			Template temp = cfg.getTemplate(name);
			temp.setEncoding("UTF-8");
			//模板输出HTML
			temp.process(map, out);
			//支持中文
			return out.toString();
		} catch (Exception e) {
			log.error("模板数据替换失败:{}", e.getMessage(), e);
			throw new RuntimeException("模板数据替换失败：" + e.getMessage());
		} finally {
			try {
				out.flush();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}
